前面我們用 Gitlab pipeline build docker image 並且推上 ECR repository,ECS service 會用 ECR repository 內對應的 image 執行 container 提供服務。那麼有新 image 後是誰會把新 image deploy 到 ECS service 上呢?總不是要手動按吧?說好的自動化呢~?
今天我們要接上 CD 自動化的最後一塊拼圖:CodePipeline。利用 CodePipeline 在 ECR repository 有新的 image 時 trigger ECS deployment。 (筆者這麼懶怎麼可能自己按
CodePipeline 是 AWS 管理的 continuous delivery 服務,讓我們可以自動化的進行各種部屬。
CodePipeline 的一個 pipeline 可以有多個 stage,每個 stage 可以執行多個 action,就像 Gitlab pipeline 的 stage 跟 job。CodePipeline 有整合其他服務,所以可以執行各種各樣的 action。
我們從最基本的擁有 Source、Build 以及 Deploy 三個 stage 的 pipeline 開始,三個 stage 主要做的事情是:
Source:從 ECR repository 取得 docker image
Build:建立 Deploy stage 需要的 metadata
Deploy:trigger ECS service 用新的 image deploy
老樣子,先用 web console 手動建立,進到 CodePipeline 的頁面:
Create pipeline,讓它自己建立需要的 Role:
新增第一個 stage Source:
我們要從 ECR 拿 image 來 deploy,所以 source provider 選 Amazon ECR、選我們放 docker image 的 repository,image tag 留空讓它用預設的 latest
即可。image tag 用 latest
表示這個 tag 的 image 有變動的時候,會 trigger pipeline 執行。我們在 day6 的 gitlab pipeline push docker image 時除了有用日期時間當 tag,也會更新 latest
的 image,這樣才能把 gitlab pipeline 跟 CodePipeline 串起來。
接著第二個 stage build:
這邊我們要用 AWS CodeBuild 執行簡單指令,來產生後面 deploy stage 需要的 metadata 檔案。
點 Create project 後會開一個新視窗來建立 CodeBuild project:
環境部份簡單使用 Ubuntu 最新版本的 image,並讓它產生需要的 IAM role。
後面 additional configuration 都不動。
Buildspec 是我們指定要執行的指令的地方,它的格式是 YAML。我們直接切到 editor 貼指令:
在 Build commands 的編輯框貼上:
version: 0.2
phases:
build:
commands:
- ContainerName="my-app"
- ImageURI=$(cat imageDetail.json | jq -r '.ImageURI')
- printf '[{"name":"CONTAINER_NAME","imageUri":"IMAGE_URI"}]' > imagedefinitions.json
- sed -i -e "s|CONTAINER_NAME|$ContainerName|g" imagedefinitions.json
- sed -i -e "s|IMAGE_URI|$ImageURI|g" imagedefinitions.json
artifacts:
files:
- imagedefinitions.json
這段指令設了兩個變數 ContainerName
跟 ImageURI
,一個是 task definition 裡 container 的名稱(my-app
)、一個從 imageDetail.json
欄位 ImageURI
來。接著在 imagedefinitions.json
裡寫入一段 json,內容有 continaer 名稱跟 image uri。這段指令的產出物(artifacts)是 imagedefinitions.json
這個檔案。
為什麼要有 build stage 指令產生 imagedefinitions.json
呢?從 ECR 拿到 image 後叫 ECS deploy 就好了啊~?
這是因為 ECS 需要 imagedefinitions.json
這個檔案取得 container 相關資訊,像是要使用的新的 image 是什麼,然後產生新的 ECS service 的 task definition revision,最後讓 ECS service 使用新的 task definition revision 來跑 task。
那麼 imageDetail.json
又是哪來的?
imageDetail.json
是 pipeline 的 ECR source action 自動產生的,它會作為 source stage 的產出物(output artifact)給下一個 stage(也就是 build stage)使用,所以我們可以在這邊拿到 imageDetail.json
。
後面 Logs 部份都不勾:
點 Continue to Codepipeline 會建立 CodeBuild project 並關閉這個新視窗。
回到 CodePipeline 可以看到已經選擇剛剛建立的 CodeBuild project:
Next 繼續~
增加最後一個 stage Deploy,deploy provider 當然選 ECS 啦~ cluster 跟 service 照著建立的填就是了~
Next 後會讓你 review 整個 CodePipeline 的設定,沒問題就 Create pipeline 吧!
pipeline 建立後,可以看它的執行過程:
順利的話,我們會看到三個 stage 都綠燈跑完表示 deploy 完成,這時候用瀏覽器開啟網站,就能看到新版程式的結果。
最後各位可以嘗試隨意改點程式碼,然後從 Gitlab 啟動一個 pipeline 看看整個從 Gitlab 到 CodePipeline 的 deploy 過程,再從 ALB DNS name 檢查新的程式碼是不是成功 deploy。一切順利的話,我們這就完成了從 Gitlab 開始的自動化 CD!(當然你可能不希望每次 push code 都 deploy 一次,就要調整 Gitlab deploy 相關 job 的觸發條件了~)